<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>垃圾回收机制</title>
</head>
<body>
    <!-- 
        Js中内存分配和回收都是自动完成的，内存在不使用的时候会被垃圾回收器自动回收

        ☆☆ 内存的生命周期：
            Js 环境中分配的内存，一般有如下的生命周期：
                内存分配：当我们声明变量、函数、对象的时候，系统会自动为他们分配内存
                内存使用：即读写内存，也就是使用变量、函数等
                内存回收：使用完毕，由垃圾回收器自动回收不在使用的内存

        说明（常数的垃圾回收是局部变量的）：
            全局变量一般不会回收（关闭页面回收）
            一般情况下局部变量的值，不用了，会被自动回收掉
            内存泄漏：程序中分配的内存由于某种原因程序未释放或无法释放叫做内存泄漏（在IE浏览器中会存在）
     -->

     <!-- =================垃圾回收机制算法说明================= -->
     <!-- 
        堆栈空间分配区别
            1、栈：由操作系统自动分配释放函数的参数值，局部变量等，基本数据类型放到栈里面
            2、堆：一般由程序员分配释放，若程序员不释放，由垃圾回收机制回收，复杂数据类型放在堆里面

            两种常见的浏览器垃圾回收算法:引用记数法和标记清除法

            # 引用记数
             IE采用的引用记数算法，定义“内存不在使用”，就是看一个对象是否有指向它的引用，没有引用了就回收对象
                算法：
                    1、跟踪记录被引用的次数
                    2、如果被引用一次，那么就记录一次，多次引用会累加 ++ 
                    3、如果减少一个引用就减一--
                    4、如果引用次数是0，则释放内存
                当栈区有地址是指向堆中的数据时，记数就加一，当没有地址指向堆区数据时，就会被回收
            他存在一个致命的问题：
                嵌套引用（循环引用）：如果两个对象相互引用，尽管他们不再使用，垃圾回收器不会进行回收，导致内存泄漏
                如果导致两个对象相互引用，尽管他们不在使用，垃圾回收器不会进行回收，导致内存泄漏

            例子：
                function fn(){
                    let a = {}
                    let b = {}
                    a.o1 = b
                    b.o1 = a
                    return '引用记数无法被回收' // 会一直存在引用，他的引用次数不可能会是0
                }
                fn()

            # 标记清除法：
                现代浏览器不再使用引用记数法，大多是基于清除算法的某些改进算法，总体思想都是一致的
                核心：
                    1、将“不在使用的对象”定义为“无法达到的对象”
                    2、就是从根部（在js中就是全局对象）出发定时扫描内存中的对象。凡是能从根部到达的对象，都是还需要使用的
                    3、那些无法从根部出发触及到的对象被标记为不在使用，稍后进行回收
                在局部变量中的数据，根部是无法被访问到的，所以在执行完成后被回收

      -->

</body>
</html>